{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "c57fdf9d",
   "metadata": {},
   "source": [
    "# 内置仿真机"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cacdea35",
   "metadata": {},
   "source": [
    "Cqlib 针对不同场景提供了两类内置仿真机，均支持多种形式的模拟输出，便于用户进行量子算法验证与测试。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6648b779",
   "metadata": {},
   "source": [
    "返回数据接口说明。\n",
    "\n",
    "| 接口 | 描述|\n",
    "|-------|----------|\n",
    "|statevector| 返回量子线路的最终状态向量（忽略测量门）。 |\n",
    "|probs| 基于状态向量计算得到的概率分布（忽略测量门）。 |\n",
    "|measure| 根据测量比特和顺序获取的测量概率分布。 |\n",
    "|sample| 根据测量比特和顺序采样得到的实验数据。 |"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1da108ab",
   "metadata": {},
   "source": [
    "## 1. 状态向量仿真机"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "004792b2",
   "metadata": {},
   "source": [
    "Cqlib内置的状态向量仿真机基于全振幅模拟方法，集成并行计算和内存优化技术，能够高效模拟中等规模量子线路，适用于量子算法在本地环境下的快速验证。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "753c8b68",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Statevector: {'000': (0.3535533905932737+0j), '001': (0.3535533905932737+0j), '010': (0.3535533905932737+0j), '011': (-0.3535533905932737+0j), '100': (0.3535533905932737+0j), '101': (0.3535533905932737+0j), '110': (0.3535533905932737+0j), '111': (-0.3535533905932737+0j)}\n",
      "Probabilities: {'000': 0.12499999999999994, '001': 0.12499999999999994, '010': 0.12499999999999994, '011': 0.12499999999999994, '100': 0.12499999999999994, '101': 0.12499999999999994, '110': 0.12499999999999994, '111': 0.12499999999999994}\n",
      "\n",
      "Measure: {'00': 0.2499999999999999, '01': 0.2499999999999999, '10': 0.2499999999999999, '11': 0.2499999999999999}\n",
      "Sample: {'10': 249, '11': 267, '01': 256, '00': 228}\n",
      "\n"
     ]
    }
   ],
   "source": [
    "from cqlib import Circuit\n",
    "from cqlib.simulator import StatevectorSimulator\n",
    "\n",
    "circuit = Circuit(3)\n",
    "for i in range(3):\n",
    "    circuit.h(i)\n",
    "    circuit.cx(i, (i + 1) % 3)\n",
    "circuit.measure(0)\n",
    "circuit.measure(2)\n",
    "\n",
    "sim = StatevectorSimulator(circuit)\n",
    "print(f\"Statevector: {sim.statevector()}\\n\"\n",
    "      f\"Probabilities: {sim.probs()}\\n\")\n",
    "\n",
    "# 根据测量门，获得 Q2 和 Q0 的测量分布和采样数据\n",
    "print(f\"Measure: {sim.measure()}\\n\"\n",
    "      f\"Sample: {sim.sample(shots=1000)}\\n\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5cf7797d",
   "metadata": {},
   "source": [
    "## 2. 基于 Torch 的仿真机"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "84489795",
   "metadata": {},
   "source": [
    "Cqlib 还内置了一款基于 PyTorch 的量子仿真后端，利用 PyTorch 的张量运算和自动微分特性，支持 GPU 加速和梯度计算，适用于全振幅模拟与变分量子算法的端到端训练流程。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "96663552",
   "metadata": {},
   "source": [
    "### 2.1 计算概率"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "710ba157",
   "metadata": {},
   "source": "`SimpleSimulator` 与状态向量仿真机类似，支持相同的四种输出形式："
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b7a41f8d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Statevector: {'000': tensor(0.3536+0.j, dtype=torch.complex128), '001': tensor(0.3536+0.j, dtype=torch.complex128), '010': tensor(0.3536+0.j, dtype=torch.complex128), '011': tensor(-0.3536+0.j, dtype=torch.complex128), '100': tensor(0.3536+0.j, dtype=torch.complex128), '101': tensor(0.3536+0.j, dtype=torch.complex128), '110': tensor(0.3536+0.j, dtype=torch.complex128), '111': tensor(-0.3536+0.j, dtype=torch.complex128)}\n",
      "Probabilities: {'000': tensor(0.1250, dtype=torch.float64), '001': tensor(0.1250, dtype=torch.float64), '010': tensor(0.1250, dtype=torch.float64), '011': tensor(0.1250, dtype=torch.float64), '100': tensor(0.1250, dtype=torch.float64), '101': tensor(0.1250, dtype=torch.float64), '110': tensor(0.1250, dtype=torch.float64), '111': tensor(0.1250, dtype=torch.float64)}\n",
      "\n",
      "Measure: {'00': tensor(0.2500, dtype=torch.float64), '01': tensor(0.2500, dtype=torch.float64), '10': tensor(0.2500, dtype=torch.float64), '11': tensor(0.2500, dtype=torch.float64)}\n",
      "Sample: {'11': 526, '01': 467, '00': 506, '10': 501}\n",
      "\n"
     ]
    }
   ],
   "source": [
    "from cqlib import Circuit\n",
    "from cqlib.simulator import SimpleSimulator\n",
    "\n",
    "circuit = Circuit(3)\n",
    "for i in range(3):\n",
    "    circuit.h(i)\n",
    "    circuit.cx(i, (i + 1) % 3)\n",
    "circuit.measure(0)\n",
    "circuit.measure(2)\n",
    "\n",
    "sim = SimpleSimulator(circuit)\n",
    "print(f\"Statevector: {sim.statevector()}\\n\"\n",
    "      f\"Probabilities: {sim.probs()}\\n\")\n",
    "\n",
    "# 根据测量门，获取 Q2 和 Q0 的测量分布和采样数据\n",
    "print(f\"Measure: {sim.measure()}\\n\"\n",
    "      f\"Sample: {sim.sample(shots=2000)}\\n\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "71a2e498",
   "metadata": {},
   "source": [
    "### 2.2 梯度计算"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e4b0d506",
   "metadata": {},
   "source": [
    "SimpleSimulator 深度融合 PyTorch 的计算图机制，支持量子线路的端到端自动微分能力，可高效执行含参数化量子门的正向模拟与反向梯度传播，适用于变分量子算法的训练任务。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "469cfa36",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Probabilities: tensor([0.2500, 0.2500, 0.2500, 0.2500], dtype=torch.float64,\n",
      "       grad_fn=<IndexBackward0>)\n",
      "\n",
      "Gradients: tensor([8.6736e-18, 3.4694e-18, 6.9389e-18])\n",
      "\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "\n",
    "from cqlib import Circuit, Parameter\n",
    "from cqlib.simulator import SimpleSimulator\n",
    "\n",
    "ps = [Parameter(f\"p{i}\") for i in range(3)]\n",
    "circuit = Circuit(3, ps)\n",
    "for i in range(3):\n",
    "    circuit.h(i)\n",
    "    circuit.rx(i, ps[i])\n",
    "circuit.measure(0)\n",
    "circuit.measure(2)\n",
    "\n",
    "params = torch.tensor([0.1, 0.2, 0.3], requires_grad=True)\n",
    "circuit.assign_parameters(params, cache_params=True)\n",
    "sim = SimpleSimulator(circuit)\n",
    "probs = sim.measure(dict_format=False)\n",
    "print(f\"Probabilities: {probs}\\n\")\n",
    "\n",
    "probs[0].backward()\n",
    "print(f\"Gradients: {params.grad}\\n\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "978a1bad",
   "metadata": {},
   "source": [
    "注意：为了启动梯度计算，在调用 assign_parameters 时需要特别设置 `cache_params = True` ，以确保模拟过程中参数绑定的可微性。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "cqlib3.10",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.16"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
